package com.example.comment.service.impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.comment.base.dto.CommentAddDTO;
import com.example.comment.base.dto.CommentQueryDTO;
import com.example.comment.base.entity.Comment;
import com.example.comment.base.vo.CommentVO;
import com.example.comment.convert.CommentConvert;
import com.example.comment.enums.AuditStatusEnum;
import com.example.comment.enums.CommentTypeEnum;
import com.example.comment.repository.CommentRepository;
import com.example.comment.service.CommentLikeService;
import com.example.comment.service.CommentService;
import com.example.comment.utils.PageResult;
import com.example.comment.utils.SystemException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.TemporalUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @author QingZeyu
 * @date 2024/5/6 11:37
 */
@Service
@Slf4j
public class CommentServiceImpl implements CommentService {
    @Resource
    private CommentRepository commentRepository;

    @Resource
    private CommentLikeService commentLikeService;

    /**
     * 回复评论分页初始页码
     * */
    private static final Integer REPLY_PAGE_NUM = 1;
    /**
     * 回复评论分页初始每页条数
     * */
    private static final Integer REPLY_SIZE_NUM = 3;

    private static final Integer ONE_DAY_HOUR = 24;
    @Override
    public PageResult<CommentVO> page(CommentQueryDTO dto) {
        Page<Comment> page = commentRepository.page(dto);
        List<CompletableFuture<CommentVO>> futureList = new ArrayList<>();
        for (Comment record : page.getRecords()) {
            CompletableFuture<CommentVO> future = CompletableFuture.supplyAsync(() -> {
                CommentVO vo = CommentConvert.INSTANCE.convertToVO(record);
                vo.setLikeFlag(commentLikeService.checkIfLike(vo.getId(), dto.getUserId(), vo.getReferenceId()));
                vo.setLikeSize(commentLikeService.getLikeSize(vo.getId(), vo.getReferenceId()));
                Page<Comment> replyPage = commentRepository.getReplyComment(record.getId(), REPLY_PAGE_NUM, REPLY_SIZE_NUM);
                List<CommentVO.CommentReplyVO> replyVOList = CommentConvert.INSTANCE.convertToReplyVOList(replyPage.getRecords());
                this.setLikeFlagAndSize(replyVOList, dto.getUserId());
                PageResult<CommentVO.CommentReplyVO> reply = PageResult.build(replyPage.getTotal(), replyVOList);
                vo.setReplyList(reply);
                return vo;
            });
            futureList.add(future);
        }
        CompletableFuture<Void> allOf = CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0]));
        allOf.join();

        List<CommentVO> resultList = futureList.stream()
                .map(CompletableFuture::join)
                .collect(Collectors.toList());

        return PageResult.build(page.getTotal(), resultList);
    }

    @Override
    public Boolean addComment(CommentAddDTO dto) {
        this.checkComment(dto);
        Comment comment = CommentConvert.INSTANCE.convertToComment(dto);
        comment.setAuditStatus(AuditStatusEnum.PENDING.name());
        comment.setShowStatus(Boolean.TRUE);
        comment.setCreateBy(dto.getUserId());
        return commentRepository.save(comment);
    }

    @Override
    public Comment getComment(Long id){
        return commentRepository.getComment(id);
    }

    @Override
    public Boolean removeComment(Long userId, Long commentId) {
        Comment comment = this.getComment(commentId);
        Assert.isTrue(Objects.nonNull(comment),() -> new SystemException("评论不存在！"));
        Assert.isTrue(Objects.equals(comment.getUserId(), userId),() -> new SystemException("您没有权限删除该评论！"));
        LocalDateTime now = LocalDateTime.now();
        Date createTime = comment.getCreateTime();
        LocalDateTime commentCreateTime = LocalDateTime.ofInstant(createTime.toInstant(), ZoneId.systemDefault());

        Duration duration = Duration.between(commentCreateTime, now);
        if (duration.toHours() <= ONE_DAY_HOUR) {
            comment.setDelFlag(Boolean.TRUE);
            return commentRepository.updateById(comment);
        }
        throw new SystemException("您只能删除1天内发布的评论！");
    }

    private void checkComment(CommentAddDTO dto){
        if (Objects.equals(dto.getType(), CommentTypeEnum.COMMENT.name())) {
            Assert.isTrue(Objects.isNull(dto.getCommentId()),() -> new SystemException("参数错误！评论不可有父评论id！"));
        }else {
            Assert.isTrue(Objects.nonNull(dto.getToUserId()), () -> new SystemException("参数错误！回复评论必须指定回复用户id！"));
            Assert.isTrue(Objects.nonNull(dto.getCommentId()),() -> new SystemException("参数错误！评论id不能为空！"));
            Assert.isTrue(Objects.nonNull(this.getComment(dto.getCommentId())),() -> new SystemException("回复评论不存在！"));
        }
    }

    private void setLikeFlagAndSize(List<CommentVO.CommentReplyVO> list,Long userId){
        for (CommentVO.CommentReplyVO vo : list) {
            vo.setLikeFlag(commentLikeService.checkIfLike(vo.getId(), userId, vo.getReferenceId()));
            vo.setLikeSize(commentLikeService.getLikeSize(vo.getId(), vo.getReferenceId()));
        }
    }
}
